package com.sprite.framework.entity.bridge;

import com.sprite.framework.entity.DataScriptStatement;
import com.sprite.framework.entity.EntityScript;
import com.sprite.framework.entity.EntityScriptExecutor;
import com.sprite.framework.entity.transaction.TransactionScript;
import com.sprite.framework.entity.util.DatabaseUtil;
import com.sprite.framework.entity.util.SqlLogUtil;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCallback;
import org.springframework.transaction.PlatformTransactionManager;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;

/**
 * spring jdbc 桥接器
 * @author Jack
 */
public class JdbcTemplateBridge implements EntityScriptExecutor{

	private JdbcTemplate jdbcTemplate;

	private PlatformTransactionManager platformTransactionManager;
	
	public JdbcTemplate getJdbcTemplate() {
		return jdbcTemplate;
	}

	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}

	public PlatformTransactionManager getPlatformTransactionManager() {
		return platformTransactionManager;
	}

	public void setPlatformTransactionManager(PlatformTransactionManager platformTransactionManager) {
		this.platformTransactionManager = platformTransactionManager;
	}

	@Override
	public int execute(EntityScript script) {
		DataScriptStatement dataScript = script.getStatement();
		String sql = dataScript.toScriptString();
		if(SqlLogUtil.openLog()){
			SqlLogUtil.log(sql);
			SqlLogUtil.log(Arrays.toString(dataScript.getParams().toArray()));
		}

		return jdbcTemplate.execute(sql, new PreparedStatementCallback<Integer>() {

			@Override
			public Integer doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException {
				List<Object> params = dataScript.getParams();
				setParams(ps, params);
				int result = ps.executeUpdate();
				/*if(EntityInsertScript.class.isInstance(script)) {
					EntityInsertScript insertScript = (EntityInsertScript)script;
					ps.
					ResultSet keys =	ps.getGeneratedKeys();
					ModelEntity modelEntity = ModelEntityUtil.getModelEntity(insertScript.getEntityName());
					if(keys != null) {
						ResultSetMetaData metaData = keys.getMetaData();
						int columnIndex = 1;
						if(keys.next()) {
							while(true) {
								String columnName = metaData.getColumnLabel(columnIndex);
								if(columnName ==  null) {
									break;
								}
								ModelField modelField = modelEntity.getFieldByColumnName(columnName);
								if(modelField != null) {
									insertScript.addGeneratedKey(modelField.getFieldName(), keys.getObject(columnIndex));
								}
								columnIndex++;
							}
						}
						
					}
				}*/
				
				return result;
			}
		});
	}

	@Override
	public <T> List<T> query(EntityScript script, Class<T> clazz) {
		DataScriptStatement statement = script.getStatement();
		String sql = statement.toScriptString();
		Object[] params = statement.getParams().toArray();
		if(SqlLogUtil.openLog()){
			SqlLogUtil.log(sql);
			SqlLogUtil.log(Arrays.toString(params));
		}

		return jdbcTemplate.query(sql,new RowToObjectMapper<T>(clazz), params);
	}

	private void setParams(PreparedStatement ps , List<Object> params) throws SQLException {
		int i = 1;
		for(Object param : params) {
			ps.setObject(i++, param);
		}
	}

	@Override
	public TransactionScript beginTransaction(boolean create) {
		SpringTransactionScript script = new SpringTransactionScript(platformTransactionManager);
		return script;
	}

	@Override
	public DatabaseUtil getDatabaseUtil() {
		DatabaseUtil util = new DatabaseUtil();
		util.setDataSource(jdbcTemplate.getDataSource());
		util.setScriptExecutor(this);
		return util;
	}
}
